/**
 * 支持的类型枚举
 */
export enum DataType {
  Array = 'Array',
  Boolean = 'Boolean',
  String = 'String',
  Number = 'Number',
  Object = 'Object',
  Function = 'Function',
  AsyncFunction = 'AsyncFunction',
  Map = 'Map',
  Set = 'Set',
  Symbol = 'Symbol',
  Date = 'Date',
  RegExp = 'RegExp',
  Promise = 'Promise',
  Null = 'Null',
  Undefined = 'Undefined',
  BigInt = 'BigInt'
}

/**
 * 获取值的具体类型
 * @param value - 要检查的值
 * @returns 返回类型字符串
 */
export function getTypeof(value: unknown): string {
  return Object.prototype.toString.call(value).slice(8, -1);
}

/**
 * 类型检查函数生成器
 * @param type - 要检查的类型
 * @returns 返回类型检查函数
 */
const createTypeChecker = (type: DataType) => (value: unknown): boolean => 
  getTypeof(value) === type;

// 基础类型检查函数
export const isArray = Array.isArray;
export const isBoolean = createTypeChecker(DataType.Boolean);
export const isString = createTypeChecker(DataType.String);
export const isNumber = (value: unknown): boolean => 
  createTypeChecker(DataType.Number)(value) && !isNaN(value as number);
export const isObject = (value: unknown): boolean => 
  createTypeChecker(DataType.Object)(value) && value !== null;
export const isFunction = (value: unknown): boolean =>
  createTypeChecker(DataType.Function)(value) || 
  createTypeChecker(DataType.AsyncFunction)(value);
export const isMap = createTypeChecker(DataType.Map);
export const isSet = createTypeChecker(DataType.Set);
export const isSymbol = createTypeChecker(DataType.Symbol);

// 扩展类型检查函数
export const isDate = createTypeChecker(DataType.Date);
export const isRegExp = createTypeChecker(DataType.RegExp);
export const isPromise = (value: unknown): boolean =>
  createTypeChecker(DataType.Promise)(value) || 
  (value instanceof Promise);
export const isNull = createTypeChecker(DataType.Null);
export const isUndefined = createTypeChecker(DataType.Undefined);
export const isBigInt = createTypeChecker(DataType.BigInt);

/**
 * 检查值是否为原始类型
 */
export const isPrimitive = (value: unknown): boolean =>
  value === null ||
  value === undefined ||
  isBoolean(value) ||
  isNumber(value) ||
  isString(value) ||
  isSymbol(value) ||
  isBigInt(value);

/**
 * 检查值是否为普通对象（不包括数组、Map等）
 */
export const isPlainObject = (value: unknown): boolean => {
  if (!isObject(value)) return false;
  const proto = Object.getPrototypeOf(value);
  return proto === null || proto === Object.prototype;
};

/**
 * 获取值的详细类型信息
 */
export const getTypeInfo = (value: unknown): { 
  type: string; 
  isPrimitive: boolean; 
  isNullable: boolean;
} => {
  const type = getTypeof(value);
  return {
    type,
    isPrimitive: isPrimitive(value),
    isNullable: value === null || value === undefined
  };
};
